public class PLLayerManager {	
	PLLayer  mLayers[];
	int mMaxTries = 4;
	
	public PLLayerManager(String name) {
		mLayers = new PLLayer[3];

		mLayers[0] = new PLLayerFeature(name);
		mLayers[1] = new PLLayerPattern(name);
		mLayers[2] = new PLLayerCognition(name);		
	}


	// give a query and response, verifies the response with all the layers and returns the confidence in the returned response 
	private float VerifyResponse(PLShape query, PLOutShape outResponse, PLOutShape outBetterMatch, int curLayer) throws CloneNotSupportedException {
		float confidence = 0;
		if (curLayer >= mLayers.length -1) {
			// we are at the last layer, Nothing more to do!
			// full confidence in the response
			return 1;
		}

		boolean responseImproved = false;
		int numTries = mMaxTries;
		PLOutShape response = (PLOutShape)outResponse.clone();
		PLOutShape betterMatch = new PLOutShape();		
		while(numTries > 0) {
			numTries--;
			betterMatch.clear();
			// ask the next layer to verify response 
			confidence = mLayers[curLayer+1] .ValidateResponse(query, response.GetShape(), betterMatch);	

			if (confidence < 0.3) {
				// the confidence is low, lets try and improve the response
				mLayers[curLayer] .ImproveResponse(query, response, betterMatch.GetShape());	
				responseImproved = true;
				continue;
			}

			betterMatch.clear();
			// we have high enough confidence, lets ask higher layers
			confidence = Math.min(confidence, VerifyResponse(query, response, betterMatch, curLayer + 1));

			// the confidence is still high after checking all higer layers, lets break
			if (confidence > 0.3) {
				break;
			}

			// if the confidence is low or shape is disallowed by higer layer, try to improve the response
			mLayers[curLayer] .ImproveResponse(query, response, betterMatch.GetShape());	
			responseImproved = true;
		}

		if (responseImproved) {
			// set the improved respose of the higher layer as a better match for the lower layer
			outBetterMatch.copyOf(response);		
		}
		
		return confidence;		
	}


	// responsibility to generate response after an agreement of all layers.
	// returns with a certain confidence.
	public float GenResponse(PLShape query, PLOutShape  outResponse) {		
		mLayers[0] .BuildResponse(query, outResponse);
		
		PLOutShape dummy = new PLOutShape();		
		float confidence = 0;
		try {
			confidence = VerifyResponse(query, outResponse, dummy, 0);
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return confidence;
	}	
}
